<?php

namespace cosocket\application;

use cosocket\system\Logger as CoreLogger;
use LogicException;

class Application
{
    public function __construct()
    {
    }

    public function run(& $params, $clientInfo)
    {
        $controller = ucfirst($params['c']);
        $action = $params['m'] . "Action";
        $class_name = __NAMESPACE__ . "\\controllers\\".$controller . "Controller";

        try {
            $obj = new $class_name($params['data'], $clientInfo);
            if (!method_exists($obj, $action)) {
                unset($obj);
                show_404("$controller/$action");
                return;
            }

            $obj->$action();
            unset($obj);
        } catch (\Exception $e) {
            unset($obj);
            $this->handleException($e);
        }
    }

    /**
     * 处理异常并输出错误信息
     */
    private function handleException(\Exception $e)
    {
        if ($e instanceof LogicException) {
            $this->logAndPrintError(
                "LogicException",
                $e,
                "exception_log"
            );
        } else if ($e->getMessage() != 'swoole exit.') {
            $this->logAndPrintError(
                "Exception",
                $e,
                "exception_log"
            );
        } else {
            echo "swoole exit.\n";
        }
    }

    /**
     * 记录日志并打印错误信息
     */
    private function logAndPrintError(string $type, \Exception $e, string $logFile)
    {
        $errorInfo = sprintf(
            "File=[%s|%s] Code=[%s], Message=[%s]",
            $e->getFile(),
            $e->getLine(),
            $e->getCode(),
            $e->getMessage()
        );

        CoreLogger::error("Catch An {$type} " . $errorInfo, $logFile);

        echo "Catch An {$type} \n";
        echo "File: " . $e->getFile() . "\n";
        echo "Line: " . $e->getLine() . "\n";
        echo "Code: " . $e->getCode() . "\n";
        echo "Message: " . $e->getMessage() . "\n";
    }
}

